
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>

//Use fuse to set sys clock to 1 MHz

volatile unsigned int ADCval;
volatile double temperature;

void usart_init (void)
{
	UCSR0B 	= 	(1<<TXEN0);//enable transmit
	UCSR0C 	= 	((1<<UCSZ01)|(1<<UCSZ00));//asynchronous mode 8b data 1MHz clock
	UBRR0 	= 	0x33;//set baud rate to 1200
}

int USART0SendByte(char u8Data, FILE *stream)
{
	if(u8Data == '\n')//check if linefeed then send carriage feed
	USART0SendByte('\r', 0);
	while(!(UCSR0A&(1<<UDRE0)));//wait until previous byte is completed
	UDR0 = u8Data;// Transmit data
	return 0;
}

void init_timer(void)
{
	TCNT1 = 0;//start value for timer1
	OCR1B = 64559;//2^16 - 1MHz/1024
	TCCR1A = (1<<COM1A0)|(1<<WGM11);
}

void startTimer(void)
{
	TCNT1 = 0;//start value for timer1
	TCCR1B = (1<<CS10)|(1<<CS12);//use pre-scalar of 1024
}

void stopTimer(void)
{
	TCCR1B = (0<<CS10)|(0<<CS12);//use pre-scalar of 0
}

void initADC(void)
{
	ADMUX = (1<<REFS0)|(1<<ADLAR);//set Vref to 5V and left justify
	ADCSRA = (1<<ADPS2)|(1<<ADATE)|(1<<ADIE)|(1<<ADEN);//set prescalar to 16 clk=62.5kHz, enable ADC interrupt
	//set auto triggering and enable ADC
	ADCSRB = (1<<ADTS2)|(1<<ADTS0);//set ADC to trigger off timer1 compare match b
}

void ADCchannelSel(void)
{
	ADMUX &= 0xE0;//use channel 0
}



uint16_t ReadADC(uint16_t ADCchannel)
{
	ADMUX = (ADMUX & 0xF0)|(ADCchannel & 0x0F);//select channel
	ADCSRA |= 1<<ADSC;//single conversion
	while(ADCSRA & (1<<ADSC));//wait for conversion
	ADCval = ADC>>6;//use only upper 10 bits of 16 bits
	return ADCval;
}

ISR(ADC_vect)
{
	stopTimer();
	TIFR1 = (1<<OCF1B);//clear timer match flag
	temperature = (double)ReadADC(0)*5/1024/0.01;//Vin=ADC*Vref/1024 and F=Vin/0.01
	printf("temperature value is %3u degrees Fahrenheit\n",(uint16_t)temperature);//print to screen
	ADCSRA 	|= 	1<<ADSC;
	startTimer();
}

int main(void)
{
	initADC();//initialize ADC
	usart_init();//initialize usart
	//set usart to output stream
	FILE usart0_str = FDEV_SETUP_STREAM(USART0SendByte, NULL, _FDEV_SETUP_RW);
	stdout = &usart0_str;
	ADCchannelSel();
	init_timer();//initialize timer1
	startTimer();//start timer 1
	sei();//enable interrupts
	
	while(1)
	{
	}
	return 0;
}
